require 'sketchup.rb'


class DynamicComponentsV1
module Classifier

  APPLIED_SCHEMA_TYPES = 'AppliedSchemaTypes'.freeze
  SCHEMA_TYPE          = 'SchemaType'.freeze
  CLASSIFICATION_TYPE  = 'CLASSIFICATION TYPE'.freeze # Translate?


  # Iterator that will report all classifier attribute for the given entity.
  #
  #   Args:
  #     entity: reference to the entity we want to report classifications for
  #
  #   Yields:
  #     path: the classifier attribute path
  #     value: the classifier attribute value
  #
  #   Returns:
  #     nil:
  def self.report_classifications(entity, &block)
    definition = self.get_definition(entity)
    return nil if definition.nil?

    for schema, schema_type in self.schemas(definition)
      schema_type_short_name = schema[SCHEMA_TYPE].split(':').last
      root = "#{schema.name}:#{schema_type_short_name}"
      # Report only top level classification, do not recurse for
      # sub-dictionaries
      yield(CLASSIFICATION_TYPE, root) # (?) Translate?
    end

    nil
  end

  # Finds all the attribute dictionaries that contain the classifier data for
  # each schema.
  #
  #   Args:
  #     entity: reference to the entity we want to get the schemas for
  #
  #   Returns:
  #     array: collection of attribute dictionaries for each schema
  def self.schemas(entity)
    data = []
    schema_types = entity.attribute_dictionary(APPLIED_SCHEMA_TYPES, false)
    if schema_types
      for schema_name in schema_types.keys
        dictionary = entity.attribute_dictionary(schema_name, false)
        data << dictionary unless dictionary.nil?
      end
    end
    data
  end

  # Iterator that will report all classifier attribute for the given dictionary.
  #
  #   Args:
  #     dictionary: reference to the dictionary we want to report
  #                 classifications for
  #
  #   Yields:
  #     path: the classifier attribute path
  #     value: the classifier attribute value
  #
  #   Returns:
  #     nil:
  def self.each_schema_attribute(schema_dictionary, path = '', &block)
    return nil unless schema_dictionary.is_a?(Sketchup::AttributeDictionary)
    # The UI doesn't expose attributes of choice type - so until that is 
    # implemented we ignore them here as well.
    if schema_dictionary['attribute_type'] == 'choice'
      return nil
    end
    value = schema_dictionary['value']
    if !value.nil?
      yield(path, value)
    end
    sub_dictionaries = schema_dictionary.attribute_dictionaries
    if sub_dictionaries
      for sub_dictionary in sub_dictionaries
        nested_path = "#{path}:#{sub_dictionary.name}"
        self.each_schema_attribute(sub_dictionary, nested_path, &block)
      end
    end
    nil
  end

  # Finds the ComponentDefinition for the given entity.
  #
  #   Args:
  #     entity: reference to the entity we want to get the definition for
  #
  #   Returns:
  #     definition: definition on success, nil on failure
  def self.get_definition(entity)
    if entity.is_a?(Sketchup::ComponentInstance)
      return entity.definition
    elsif entity.is_a?(Sketchup::Group)
      # (i) group.entities.parent should return the definition of a group.
      # But because of a SketchUp bug we must verify that group.entities.parent
      # returns the correct definition. If the returned definition doesn't
      # include our group instance then we must search through all the
      # definitions to locate it.
      if entity.entities.parent.instances.include?(entity)
        return entity.entities.parent
      else
        Sketchup.active_model.definitions.each { |definition|
          return definition if definition.instances.include?(entity)
        }
      end
    end
    return nil
  end

end # module
end # class